/**
 * 
 */
package cn.agiledata.bank.facade;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import uk.ltd.getahead.dwr.WebContextFactory;

import cn.agiledata.bank.account.dao.IAccountDAO;
import cn.agiledata.bank.account.service.AccountSummary;
import cn.agiledata.bank.account.service.IAccountConst;
import cn.agiledata.bank.account.service.IAccountService;
import cn.agiledata.bank.common.exception.BusinessException;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.common.util.SecurityUtil;
import cn.agiledata.bank.common.util.UniqueIdentityUtil;
import cn.agiledata.bank.facade.form.FormActivate;
import cn.agiledata.bank.facade.form.FormRegister;
import cn.agiledata.bank.facade.helper.AuthorizationHelper;
import cn.agiledata.bank.facade.helper.CodationHelper;
import cn.agiledata.bank.facade.helper.NotificationHelper;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.myspace.exception.MySpaceException;


/**
 * @author 马贤波
 * 
 * Apr 26, 2006
 */
public class ServiceFacade {

	public static final String SESS_VERICODE = "sys_sess_vericode";

	public static final String SESS_SMS_VERICODE = "sys_sess_sms_vericode";

	public static final String SESS_SMS_MOBILE = "sys_sess_sms_mobile";

	/** 按表单存放校验码 */
	public static String genVericode() {
		String code = UniqueIdentityUtil.createRandomString(4);
		return code;
	}

	private static HttpSession getSession() {
		HttpSession sess = null;

		try {
			sess = WebContextFactory.get().getSession();
		} catch (RuntimeException e) {
			e.printStackTrace();
		}

		return sess;
	}

	public static void setSessionAttribute(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	public static Object getSessionAttribute(String key) {
		return getSession().getAttribute(key);
	}

	public static void removeSessionAttribute(String key) {
		getSession().removeAttribute(key);
	}

	private void refreshVericode() {
		String vericode = genVericode();
		setSessionAttribute(SESS_VERICODE, vericode);
	}

	private String[] calSectionGroups(String section) {
		if (section == null) {
			section = "";
		}
		String[] tuple = section.split("\\$");
		String[] result = new String[tuple.length + 1];
		result[0] = "";
		result[result.length - 1] = section;

		for (int i = 1; i < tuple.length; i++) {
			result[i] = result[i - 1] + tuple[i - 1] + "$";
		}

		return result;
	}

	protected Properties dispatcher;

	public void setDispatcher(Properties routers) {
		this.dispatcher = routers != null ? routers : new Properties();
	}

	public AccountSummary getUserInternal() {
		AccountSummary user = (AccountSummary) getSessionAttribute(Constant.SESSION_ACCOUNT_SUMMARY);

		return user;
	}

	protected AccountSummary checkUser(String service, Long domain) throws BusinessException {
		AccountSummary user = this.getUserInternal();

		if (user == null) {
			// 用户尚未登录
			throw BusinessException.NOT_LOGON;
		}

		if (service != null && !user.getUser().getServiceAuthors().contains(service)) {
			// 用户没有相应的功能权限
			throw BusinessException.NOT_PERMIT_SERVICE;
		}

		if (domain != null && !domain.equals(user.getUser().getDomainAuthen())) {
			// 用户没有相应的数据权限
			throw BusinessException.NOT_PERMIT_DOMAIN;
		}

		return user;
	}

	protected AccountSummary checkUser(String service) throws BusinessException {
		return this.checkUser(service, null);
	}

	protected AccountSummary checkUser() throws BusinessException {
		return this.checkUser(null, null);
	}

	/** 主动转发，多发生在页面链接中 */
	public String forward(String section, String params) throws BusinessException {

		if (section == null || section.trim().equals("")) {
			section = "welcome";
		}

		String path = this.dispatcher.getProperty(section);
		if (path == null) {
			path = this.dispatcher.getProperty("404", "");
		}

		boolean iframe = false;
		if (path.length() > 0 && path.charAt(0) == '_') {
			path = path.substring(1);
			iframe = true;
		}

		// 判断是否是需校验的页面
		if (path.indexOf("[auth]") == 0) {
			boolean access = false;

			path = path.replaceAll("\\[auth\\]", "");
			IUserSummary user = this.getUser();
			if (user == null) {
				throw BusinessException.NOT_LOGON;
			}
			List sections = user.getSectionAuthors();
			String[] groups = this.calSectionGroups(section);
			for (int i = 0; i < groups.length; i++) {
				if (sections.contains(groups[i])) {
					access = true;
					break;
				}
			}

			if (!access) {
				throw BusinessException.NOT_PERMIT_SECTION;
			}

		}

		if (params == null) {
			params = "";
		}
		if ("".equals(params.trim())) {
			params = null;
		}

		if (params != null) {
			path += "?" + params;
		}

		String content = null;
		try {
			if (iframe) {
				setSessionAttribute(Constant.SESSION_IFRAME_PATH, path);
				content = WebContextFactory.get().forwardToString(this.dispatcher.getProperty("iframe"));
			} else {
				content = WebContextFactory.get().forwardToString(path);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw BusinessException.INFRA_FAILURE;
		}

		return content;
	}

	private IAccountService accountService;

	public IUserSummary getUser() {
		AccountSummary user = this.getUserInternal();

		// 需要更新Vericode
		this.refreshVericode();

		if (user == null) {
			return null;
		}

		return user.getUser();
	}

	public Date getLastvisit() {
		AccountSummary user = this.getUserInternal();

		if (user == null) {
			return null;
		}

		return user.getLastvisit();
	}


	/**
	 * 手机注册后激活email
	 * 
	 * @param form
	 * @return
	 * @throws BusinessException
	 */
	public String sendActivateMailAfterRegister(Map form) throws BusinessException {
		String email = (String) form.get("email");
		String project = (String) form.get("project");
		AccountSummary accountSummary = this.checkUser();
		long accountId = accountSummary.getAccountId();
		try {
            this.accountService.sendActivateMailAfterRegister(email, new Long(accountId), project);
        } catch (MySpaceException e) {
            e.printStackTrace();
        }
		return "";
	}
	
	
	//向手机发送申请重置密码的确认码
	public void sendResetPasswordCodeSms(String mobile, String pwdType) throws MySpaceException {
		Account account = this.accountDAO.findAccountBySign(mobile);
		
		if (account==null) {
			throw BusinessException.RESET_PWD_ACCOUNT_NOT_EXIST;
		}
		
		String resetCode = this.codation.generateMobileSMSVericode();
		String code = pwdType + ",m," + resetCode;
		account.setResetPwdCode(code);
		
		this.accountDAO.updateAccount(account);
		
		String passwordType = "";
		if (pwdType.equals(IAccountConst.RESET_PWD_TYPE_LOGIN)) {
			passwordType = "登录";
		} else if (pwdType.equals(IAccountConst.RESET_PWD_TYPE_PAY)) {
			passwordType = "支付";
		} else if (pwdType.equals(IAccountConst.RESET_PWD_TYPE_IVR_LOGIN)) {
			passwordType = "电话账户登录";
		} else if (pwdType.equals(IAccountConst.RESET_PWD_TYPE_IVR_PAY)) {
			passwordType = "电话账户支付";
		}
		
		Map map = new HashMap();
    	map.put("passwordType", passwordType);
    	map.put("resetCode", resetCode);
    	this.notification.applyResetPasswordBySMS(mobile, map);
	}

	public String userActivate(FormActivate form) throws BusinessException {

		String email = form.getEmail();
		String activeCode = form.getActiveCode();

		try {
            this.accountService.userActivate(email, activeCode);
        } catch (MySpaceException e) {
            e.printStackTrace();
        }
		return "";

	}

	public String getRemoteAddr() {
		HttpServletRequest req = WebContextFactory.get().getHttpServletRequest();
		return req.getRemoteAddr();
	}
	
	//申请绑定手机，发送验证码
    public void smsVerify(Map form) throws MySpaceException {

        String mobile = (String) form.get("register_mobile");
        String paypass = (String) form.get("paypass");
        Long id = (Long) form.get("accountId");
        if (mobile == null) {
            throw MySpaceException.EMPTY_MOBILE_ERROR;
        }
        Account ac = this.accountDAO.findAccountBySign(mobile);
        if (ac != null) {//已注册手机
            throw MySpaceException.REGISTER_MOBILE_DUPLICATED;
        }
        //生成8位手机验证码
        String vericode = this.codation.generateMobileSMSVericode();
        Account av = this.accountDAO.getAccountById(id);
        
        String payPassword = av.getPayPassword();
        if (!payPassword.equals(SecurityUtil.encryptoMD5String(paypass))) {//支付密码错误
            throw MySpaceException.PAYPASS_ERROR;
        }
        av.setMobile(mobile);
        av.setMobActiveCode(vericode);
        av.setMobStatus(Constant.ACCOUNT_STATE_UNACTIVATED);
        av.setUpdateUser(id.toString());
        av.setUpdateTime(new Date());
        
        form.put("time", DateUtil.date2String(av.getUpdateTime()));
        form.put("describe", "绑定当前手机号码");
        form.put("vericode", vericode);
        form.put("codeType", "激活码");
        try {
			this.accountDAO.updateAccount(av);
			this.notification.verifyMobileBySMS(mobile, form);
		} catch (Exception e) {
			e.printStackTrace();
		}
       
    }
    
	public void smsVerify1(Map form) throws MySpaceException {

		String mobile = (String) form.get("register_mobile");
		if (mobile == null) {
			throw BusinessException.INFORMAL_FORM;
		}

		Account ac = this.accountDAO.findAccountBySign(mobile);
		if (ac != null) {
			throw BusinessException.REGISTER_MOBILE_DUPLICATED;
		}

		String vericode = this.codation.generateMobileSMSVericode();
		form.put("time", DateUtil.date2String(new Date()));
		form.put("vericode", vericode);
		form.put("describe","注册当前手机号码");
		form.put("codeType", "激活码");
        
		setSessionAttribute(SESS_SMS_VERICODE, vericode + "#" + mobile);
		setSessionAttribute(SESS_SMS_MOBILE, mobile);
		this.notification.verifyMobileBySMS(mobile, form);

	}
	
	public String smsVerify2(Map form) throws MySpaceException {

		String mobile = (String) form.get("register_mobile");
		if (mobile == null) {
			throw BusinessException.INFORMAL_FORM;
		}
		String vericode = this.codation.generateMobileSMSVericode1();
		form.put("time", DateUtil.date2String(new Date()));
		form.put("vericode", vericode);
		form.put("describe","注册当前手机号码");
		form.put("codeType", "激活码");
		this.notification.verifyMobileBySMS(mobile, form);
		return vericode;
	}
	/**
	 * 新的手机验证
	 * 
	 * @param form
	 * @return
	 * @throws BusinessException
	 */
	public String mobileConfirm(FormRegister form) throws BusinessException {
		String vericode = form.getVericode();
		if (vericode == null) {
			throw BusinessException.INFORMAL_FORM;
		}
		String snap = (String) getSessionAttribute(SESS_SMS_VERICODE);
		if (snap == null) {
			throw BusinessException.NOT_SMS_SUBMIT;
		}
		String[] tuple = snap.split("#");

		if (!vericode.equals(tuple[0])) {
			throw BusinessException.WRONG_SMS_CONFIRM;
		}

		String mobile = tuple[1];
		setSessionAttribute(SESS_SMS_MOBILE, mobile);
		return mobile;
	}
	
	//给手机发送取消验证码
	public void sendToCancel(long accountId) throws MySpaceException {
		sendToCancel(accountId, false);
	}

	//发送手机取消验证码(取消手机，或取消Email)
    public void sendToCancel(long accountId, boolean toCancelEmail) throws MySpaceException {
        Account ac = null ;
        try {
            ac = this.accountDAO.getAccountById(new Long(accountId));
        } catch (RuntimeException e) {
            throw BusinessException.INFRA_FAILURE ;
        }
        String mobile = ac.getMobile();
        String vericode = this.codation.generateMobileSMSVericode();
        ac.setMobActiveCode(vericode);
        ac.setUpdateUser(new Long(accountId).toString());
        ac.setUpdateTime(new Date());
        this.accountDAO.updateAccount(ac);
        Map form=new HashMap();
        
        form.put("time",DateUtil.date2String(ac.getUpdateTime()));
        form.put("describe", "取消绑定当前手机号码");
        if (toCancelEmail) {
        	form.put("describe", "取消绑定邮箱" + ac.getEmail());
        }
        form.put("vericode", vericode);
        form.put("codeType", "确认码");
        this.notification.verifyMobileBySMS(mobile, form);
    }
    
    //重发验证码
    public void reSendToActive(long accountId) throws MySpaceException {
        Account ac = null ;
        try {
            ac = this.accountDAO.getAccountById(new Long(accountId));
        } catch (RuntimeException e) {
            throw BusinessException.INFRA_FAILURE ;
        }
        String mobile = ac.getMobile();
        String vericode = this.codation.generateMobileSMSVericode();
        ac.setMobActiveCode(vericode);
        ac.setUpdateUser(new Long(accountId).toString());
        ac.setUpdateTime(new Date());
        this.accountDAO.updateAccount(ac);
        
        Map form=new HashMap();
        form.put("time",DateUtil.date2String(ac.getUpdateTime()));
        form.put("describe", "绑定当前手机号码");
        form.put("vericode", vericode);
        form.put("codeType", "激活码");
        this.notification.verifyMobileBySMS(mobile, form);
    }
	//验证手机
	public String assignMobile(Map form) throws MySpaceException {
        this.smsConfirm(form);

		return (String) form.get("mobile");
	}

    public void smsConfirm(Map form) throws MySpaceException {
        this.accountService.userActivateToMob(form);
    }

	public void unsetMobile() throws BusinessException {
		AccountSummary user = this.checkUser();
		user.setAccountMobile();
	}

	public void unsetEmail() throws BusinessException {
		AccountSummary user = this.checkUser();
		user.setAccountEmail();
	}

	public List getSubAccountDigister() throws BusinessException {
		AccountSummary user = this.checkUser();

		return user.getSubAccountDigisters();
	}

	public long currentSubAccount() throws BusinessException {
		AccountSummary user = this.checkUser();

		return user.getSelectedSubAccountId();
	}

	public void selectSubAccount(long subId) throws BusinessException {
		AccountSummary user = this.checkUser();

		user.setSelectedSubAccountId(subId);
	}

	/**
	 * @return Returns the accountService.
	 */
	public IAccountService getAccountService() {
		return accountService;
	}

	/**
	 * @param accountService
	 *            The accountService to set.
	 */
	public void setAccountService(IAccountService accountService) {
		this.accountService = accountService;
	}

	private NotificationHelper notification;

	private AuthorizationHelper authorization;

	private CodationHelper codation;

	private IAccountDAO accountDAO;

	public void pushArguments(Map args) {
		setSessionAttribute(Constant.SESSION_PAGE_ARGUMENTS, args);
	}

	public Map popArguments() {
		Map args = (Map) getSessionAttribute(Constant.SESSION_PAGE_ARGUMENTS);
		return args;
	}

	public NotificationHelper getNotification() {
		return notification;
	}

	public void setNotification(NotificationHelper notification) {
		this.notification = notification;
	}

	public AuthorizationHelper getAuthorization() {
		return authorization;
	}

	public void setAuthorization(AuthorizationHelper authorization) {
		this.authorization = authorization;
	}

	public CodationHelper getCodation() {
		return codation;
	}

	public void setCodation(CodationHelper codation) {
		this.codation = codation;
	}

	public IAccountDAO getAccountDAO() {
		return accountDAO;
	}

	public void setAccountDAO(IAccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}

}
